package com.sdses.weather.config.mapping;


import cn.hutool.core.util.StrUtil;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import com.sdses.weather.config.WeatherProviderSchemaConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class WeatherMappingUtil {

    //    // 字段缓存：提升反射性能
    private static final ConcurrentHashMap<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();

    // ==================== 提取数据列表 ====================
    public static List<Map<String, Object>> extractDataList(
            String json,
            WeatherProviderSchemaConfig.ProviderConfig providerCfg,
            WeatherProviderSchemaConfig.DataTypeConfig typeConfig) {

        if (json == null || json.trim().isEmpty() || typeConfig.getArrayPaths() == null || typeConfig.getArrayPaths().isEmpty()) {
            return new ArrayList<>();
        }

        // 非数组模式：提取单个对象
        if (!typeConfig.isArrayFlag()) {
            String singlePath = typeConfig.getArrayPaths().get(0); // fallback 到第一个
            if (StrUtil.isBlank(singlePath)) return Collections.emptyList();

            String resolvedPath = resolvePlaceholders(singlePath, providerCfg);
            Map<String, Object> obj = extractObject(json, resolvedPath);
            return obj != null ? Collections.singletonList(obj) : Collections.emptyList();
        }

        // 数组模式：多路径 fallback
        for (String pathTemplate : typeConfig.getArrayPaths()) {
            if (pathTemplate == null || pathTemplate.trim().isEmpty()) {
                continue;
            }
            String resolvedPath = resolvePlaceholders(pathTemplate, providerCfg);
            try {
                Object raw = readJsonPath(json, resolvedPath, Object.class);
                if (raw == null) {
                    continue;
                }
                List<Map<String, Object>> result = convertToList(raw);
                if (result != null && !result.isEmpty()) {
//                    log.debug("成功提取数据，路径: {}", resolvedPath);
//                    if (typeConfig.isFlatten()) {
//                        return flattenNestedList(result);
//                    }
                    return result;
                }
            } catch (Exception e) {
                log.error("JSONPath 失败: {}", resolvedPath);
            }
        }

        log.debug("All JSONPath fallbacks failed for provider={}, type={}", providerCfg, typeConfig);
        return Collections.emptyList();
    }

    // ----------------------- JSON 提取 -----------------------
    public static Map<String, Object> extractObject(String json, String jsonPath) {
        if (StrUtil.isEmpty(json) || StrUtil.isEmpty(jsonPath)) {
            return null;
        }

        try {
            ReadContext context = JsonPath.parse(json);
            Object obj = context.read(jsonPath);

            if (obj == null) {
                return null;
            }

            // 1. 如果是 Map，尝试安全转换
            if (obj instanceof Map) {
                return castToMap((Map<?, ?>) obj);
            }

            // 2. 如果是 List，取第一个 Map 类型的元素
            if (obj instanceof List) {
                List<?> list = (List<?>) obj;
                for (Object item : list) {
                    if (item instanceof Map) {
                        return castToMap((Map<?, ?>) item);
                    }
                }
                return null; // List 中没有 Map
            }

            // 3. 基本类型，包装
            return Collections.singletonMap("value", obj);

        } catch (Exception e) {
            log.error("JSONPath extractObject failed for path: {}", jsonPath, e);
            return null;
        }
    }


    public static List<Map<String, Object>> convertToList(Object obj) {
        if (obj == null) return Collections.emptyList();

        if (obj instanceof List) {
            List<?> list = (List<?>) obj;
            List<Map<String, Object>> result = new ArrayList<>(list.size());
            for (Object item : list) {
                if (item instanceof Map) {
                    Map<String, Object> map = castToMap((Map<?, ?>) item);
                    if (map != null) {
                        result.add(map);
                    }
                }
            }
            return result;
        } else if (obj instanceof Map) {
            Map<String, Object> map = castToMap((Map<?, ?>) obj);
            return map != null ? Collections.singletonList(map) : Collections.emptyList();
        } else {
            return Collections.singletonList(Collections.singletonMap("value", obj));
        }
    }


    // ==================== 映射单个对象 ====================

    // ==================== 工具方法 ====================

    public static <T> T readJsonPath(String json, String jsonPath, Class<T> targetType) {
        if (!StringUtils.hasText(json) || !StringUtils.hasText(jsonPath)) {
            return null;
        }
        try {
            DocumentContext context = JsonPath.parse(json);
            return context.read(jsonPath, targetType);
        } catch (InvalidPathException e) {
            log.debug("JSONPath not found: {}", jsonPath);
            return null;
        } catch (Exception e) {
            log.warn("JSONPath read failed: {}", jsonPath, e);
            return null;
        }
    }

    public static String resolvePlaceholders(String path, WeatherProviderSchemaConfig.ProviderConfig config) {
        if (!StringUtils.hasText(path) || config == null) return path;
        String result = path;
        if (result.contains("${basePath}")) {
            result = result.replace("${basePath}", config.getBasePath());
        }
        // 可扩展其他变量：${root}, ${data} 等
        return result;
    }

    public static String joinJsonPath(String base, String path) {
        if (base.endsWith(".") || path.startsWith(".")) {
            return base + path;
        }
        return base + "." + path;
    }

    public static String getTargetFieldName(WeatherProviderSchemaConfig.FieldMapping field) {
        return field.getJava() != null ? field.getJava() : field.getJson();
    }

    public static <T> T instantiate(Class<T> clazz) throws Exception {
        if (clazz == null) {
            return null;
        }
        return clazz.getDeclaredConstructor().newInstance();
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> castToMap(Map<?, ?> map) {
        if (map == null || map.isEmpty()) return null;
        if (map.keySet().iterator().next() instanceof String) {
            return (Map<String, Object>) map;
        }
        return null;
    }

    public static  Field findField(Class<?> clazz, String fieldName) {
        return FIELD_CACHE
                .computeIfAbsent(clazz, k -> {
                    Map<String, Field> map = new HashMap<>();
                    Class<?> current = k;
                    while (current != null) {
                        for (Field field : current.getDeclaredFields()) {
                            if (!map.containsKey(field.getName())) { // 避免子类覆盖父类时重复
                                map.put(field.getName(), field);
                                if (!field.isAccessible()) {
                                    field.setAccessible(true); // ✅ 提前开启
                                }
                            }
                        }
                        current = current.getSuperclass();
                    }
                    return map;
                })
                .get(fieldName);
    }

}
